www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char16/Q/QComboBox.cpp
/************************************ REVISION LOG ENTRY Revision By: Mihai Filimon Revised on 9/16/98 2:20:27 PM Comments: QComboBox.cpp : implementation file ************************************/ #include "stdafx.h" #include "QComboBox.h" #include <math.h> #include <afxpriv.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CQComboBox #define NotifyWindow(pWnd,message,wParam,lParam) if (pWnd) pWnd->SendMessage(message, (WPARAM)wParam, (LPARAM)lParam) CBrush CQComboBox::m_brBkGnd(defaultRGBBkGnd); CFont CQComboBox::m_font; CMap<CQComboBox*,CQComboBox*, BOOL, BOOL> CQComboBox::m_mapUnloadedQCombos; static const LOGFONT logFontPages = { /*LONG lfHeight*/8, /*LONG lfWidth*/0, /*LONG lfEscapement*/0, /*LONG lfOrientation*/0, /*LONG lfWeight*/FW_NORMAL, /*BYTE lfItalic*/FALSE, /*BYTE lfUnderline*/FALSE, /*BYTE lfStrikeOut*/FALSE, /*BYTE lfCharSet*/ANSI_CHARSET, /*BYTE lfOutPrecision*/0, /*BYTE lfClipPrecision*/0, /*BYTE lfQuality*/DEFAULT_QUALITY, /*BYTE lfPitchAndFamily*/DEFAULT_PITCH, /*CHAR lfFaceName[LF_FACESIZE]*/_T("MS Sans Serif") }; // Function name : CQComboBox::CQComboBox // Description : default constuctor // Return type : CQComboBox::CQComboBox(TLine fctLine, TLinePartial fctLinePartial, LPARAM lParam) { m_lParam = lParam; m_QuickLoader.SetParent(this); RegClassQComboBox(); m_pListBox = NULL; m_pEdit = NULL; m_bCaptured = FALSE; m_fctLine = fctLine; m_fctLinePartial = fctLinePartial; m_nCountVisible = 0; SetRateWidth(0.0); SetMultipleHeight(); m_fctLoadFunction = LoadPartialListBox; m_mapUnloadedQCombos[this] = !IsAlreadyLoad(); //When you callthe contructor, you need to attach two function. //The first, for giving line number nIndex //The second, for fiving numer of line which start with a given string. // If you don't write that functions, especialy m_fctLine, you will have some suprises ASSERT(m_fctLine); } // Function name : CQComboBox::~CQComboBox // Description : virtual destructor // Return type : CQComboBox::~CQComboBox() { m_mapUnloadedQCombos.RemoveKey(this); } BEGIN_MESSAGE_MAP(CQComboBox, CWnd) //{{AFX_MSG_MAP(CQComboBox) ON_WM_DESTROY() ON_WM_LBUTTONDOWN() ON_WM_WINDOWPOSCHANGED() ON_WM_PAINT() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_SETFOCUS() ON_WM_CREATE() ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CQComboBox message handlers UINT CQComboBox::m_nSelChange = NULL; UINT CQComboBox::m_nLoading = NULL; UINT CQComboBox::m_nLoaded = NULL; // Function name : CQComboBox::RegClassQComboBox // Description : Register this window class // Return type : BOOL BOOL CQComboBox::RegClassQComboBox() { WNDCLASS wndClass; wndClass.style = CS_DBLCLKS; wndClass.lpfnWndProc = ::DefWindowProc; wndClass.cbClsExtra = NULL; wndClass.cbWndExtra = NULL; wndClass.hInstance = AfxGetInstanceHandle(); wndClass.hIcon = NULL; wndClass.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW); wndClass.hbrBackground = (HBRUSH)m_brBkGnd; wndClass.lpszMenuName = NULL; wndClass.lpszClassName = wndClassName; BOOL bResult = AfxRegisterClass(&wndClass); if (bResult) { if (!m_nSelChange) m_nSelChange = RegisterWindowMessage(defaultSelChange); if (!m_nLoading) m_nLoading = RegisterWindowMessage(defaultLoading); if (!m_nLoaded) m_nLoaded = RegisterWindowMessage(defaultLoaded); if (!m_font.GetSafeHandle()) { //At the first call set the new font m_font.CreateFontIndirect(&logFontPages); } } return bResult; } CQComboBox* CQComboBox::m_pActiveMCBox = NULL; CQComboBox::CWindowProcs CQComboBox::m_wndProcs; // Function name : CQComboBox::ListBoxWindowProc // Description : ListControl window procedure // Return type : LRESULT CALLBACK // Argument : HWND hWnd // Argument : UINT nMsg // Argument : WPARAM wParam // Argument : LPARAM lParam LRESULT CALLBACK CQComboBox::ListBoxWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { if (CQComboBox* pOwner = CQComboBox::m_pActiveMCBox) if (!pOwner->ForwardMessage(nMsg, wParam, lParam)) return NULL; return CallWindowProc( CQComboBox::m_wndProcs.GetOldListBoxProcedure(hWnd), hWnd, nMsg, wParam, lParam ); } // Function name : CQComboBox::ParentWindowProc // Description : Parent window procedure. // Return type : LRESULT CALLBACK // Argument : HWND hWnd // Argument : UINT nMsg // Argument : WPARAM wParam // Argument : LPARAM lParam LRESULT CALLBACK CQComboBox::ParentWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { CQComboBox* pOwner = CQComboBox::m_pActiveMCBox; CQComboBox* pFirst = GetFirstQComboBox(); { switch (nMsg) { case WM_KICKIDLE: { //Start to load items, after 3 seconds. if (pFirst) pFirst->SetTimer(QIDTIMERSTARTLOADITEMS, QTIMESTARTLOADITEMS, NULL); break; } case WM_COMMAND: case WM_SYSCOMMAND: case WM_LBUTTONDOWN: case WM_NCLBUTTONDOWN: { if (pFirst) { pFirst->KillTimer(QIDTIMERSTARTLOADITEMS); pFirst->KillTimer(QIDTIMERLOADITEMS); }; if (pOwner) { BOOL bDropped = pOwner->IsDropedDown(); pOwner->DropDown(FALSE); if (nMsg == WM_COMMAND) if (LOWORD(wParam) == IDOK) { pOwner->SelectCurrentItem(); return FALSE; } else if (LOWORD(wParam) == IDCANCEL) if (bDropped) return FALSE; break; } } } }; WNDPROC wndProc = CQComboBox::m_wndProcs.GetOldParentProcedure(hWnd); ASSERT (wndProc); return CallWindowProc( wndProc, hWnd, nMsg, wParam, lParam ); } // Function name : CQComboBox::EditWindowProc // Description : Edit window procedure // Return type : LRESULT CALLBACK // Argument : HWND hWnd // Argument : UINT nMsg // Argument : WPARAM wParam // Argument : LPARAM lParam LRESULT CALLBACK CQComboBox::EditWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { CQComboBox* pOwner = CQComboBox::m_pActiveMCBox; switch (nMsg) { case WM_SETFOCUS: { CQComboBox::m_pActiveMCBox = (CQComboBox*)CWnd::FromHandle(::GetParent(hWnd)); break; } case WM_KILLFOCUS: { if (pOwner) { pOwner->DropDown(FALSE); CQComboBox::m_pActiveMCBox = NULL; } break; } case WM_KEYDOWN: case WM_SYSKEYDOWN: { int nStep = 0; if (pOwner) switch ((int) wParam) { case VK_NEXT: { if (nStep == 0) nStep = +pOwner->GetVisibleCount(); } case VK_PRIOR: { if (nStep == 0) nStep = -pOwner->GetVisibleCount(); } case VK_UP: { if (nStep == 0) nStep = -1; } case VK_DOWN: { if (nStep == 0) nStep = +1; if (abs(nStep) > 1 || ((abs(nStep) == 1) && GetAsyncKeyState(VK_MENU) >= 0)) { pOwner->LoadPartial(pOwner->m_QuickLoader.GetItemLine(pOwner->GetCurrentItem()) + nStep, nStep/abs(nStep) * pOwner->GetVisibleCount()); pOwner->SetCurrentItem(pOwner->GetCurrentItem() + nStep); pOwner->SelectCurrentItem(); break; } } case defaultDropDownKey: { pOwner->DropDown(!pOwner->IsDropedDown()); break; } } break; } } return CallWindowProc( CQComboBox::m_wndProcs.GetOldEditProcedure(hWnd), hWnd, nMsg, wParam, lParam ); } // Function name : CQComboBox::OnInit // Description : Init the control // Return type : BOOL BOOL CQComboBox::OnInit() { // You must already attach a function who give me a line. ASSERT (m_fctLine != NULL); ASSERT (m_font.GetSafeHandle()); SetFont(&m_font); ModifyStyle(WS_OVERLAPPED , WS_TABSTOP); m_pEdit = new CEdit(); m_pListBox = new CListBox(); if (m_pEdit->Create(WS_CHILD | WS_VISIBLE | defaultEditStyle, CRect(0,0,0,0), this, IDEDIT )) { ModifyStyleEx(0, WS_EX_STATICEDGE); m_pEdit->SetFont(&m_font); if (m_pListBox->Create(WS_BORDER | WS_CHILD | defaultListBoxStyle , CRect(0,0,0,0), GetDesktopWindow(), IDListBox)) { m_pListBox->SetFont(&m_font); //Set the refernce to this object in user data dword ::SetWindowLong(m_pListBox->m_hWnd, GWL_USERDATA, (long)this); ::SetWindowLong(m_pListBox->m_hWnd, GWL_STYLE, GetWindowLong(m_pListBox->m_hWnd, GWL_STYLE) | WS_CLIPSIBLINGS | WS_OVERLAPPED); m_pListBox->ModifyStyleEx(0, WS_EX_TOOLWINDOW); m_pListBox->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE); ListView_SetExtendedListViewStyle(m_pListBox->m_hWnd, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); Resize(); m_wndProcs.AddEdit(GetEdit(), EditWindowProc); m_wndProcs.AddListBox(GetListBox(), ListBoxWindowProc); m_wndProcs.AddParent(GetParent(), ParentWindowProc); m_nCountVisible = GetVisibleCount(); return TRUE; } } return FALSE; } // Function name : CQComboBox::PreSubclassWindow // Description : Call to subclass window // Return type : void void CQComboBox::PreSubclassWindow() { CWnd::PreSubclassWindow(); OnInit(); } // Function name : CQComboBox::OnDestroy // Description : Remove all dependent datas. // Return type : void void CQComboBox::OnDestroy() { CWnd::OnDestroy(); m_wndProcs.RemoveEdit(GetEdit()); m_wndProcs.RemoveListBox(GetListBox()); m_wndProcs.RemoveParent(GetParent()); if (CListBox* pList = GetListBox()) delete pList; if (CEdit* pEdit = GetEdit()) delete pEdit; m_pListBox = NULL; m_pEdit = NULL; } // Function name : CQComboBox::GetListBox // Description : return the list control for // Return type : CListBox* CListBox* CQComboBox::GetListBox() { return m_pListBox; } // Function name : CQComboBox::GetEdit // Description : retirn pointer to edit control inside of thsi control // Return type : CEdit* CEdit* CQComboBox::GetEdit() { return m_pEdit; } // Function name : CQComboBox::DrawButton // Description : Draw down button // Return type : void // Argument : CDC * pDC // Argument : CRect r // Argument : BOOL bDown void CQComboBox::DrawButton(CDC * pDC, CRect r, BOOL bDown) { CPen penWhite(PS_SOLID,1,RGB(255,255,255)); CPen penBlack(PS_SOLID,1,RGB(0,0,0)); pDC->FrameRect(r,&CBrush(RGB(128,128,128))); if (!bDown) { pDC->SelectObject(&penWhite); pDC->MoveTo(r.left, r.bottom - 2); pDC->LineTo(r.left, r.top); pDC->LineTo(r.right - 1, r.top); } CBitmap bitmapOEM; if (bitmapOEM.LoadOEMBitmap(OBM_COMBO)) { CDC dcMem; if (dcMem.CreateCompatibleDC(pDC)) { BITMAP b; bitmapOEM.GetBitmap(&b); int leftC = max((r.Width() - b.bmWidth) / 2,1); int topC = max((r.Height() - b.bmHeight) / 2,1); if (bDown) { leftC++; topC++; } CBitmap* pOldBitmap = dcMem.SelectObject(&bitmapOEM); pDC->BitBlt(r.left + leftC, r.top + topC, r.Width() - (leftC + 1), r.Height() - (topC), &dcMem, 0,0, SRCCOPY); pOldBitmap = dcMem.SelectObject(pOldBitmap); } } } // Function name : CQComboBox::OnPaint // Description : On Draw function // Return type : void void CQComboBox::OnPaint() { CPaintDC dc(this); // device context for painting CRect r; GetClientRect(r); r.right--; dc.MoveTo(r.left, r.bottom); dc.LineTo(r.left, r.top); dc.LineTo(r.right, r.top); dc.LineTo(r.right, r.bottom); r.left = r.right - defaultSizeDX; r.InflateRect(0,-2);r.bottom++;r.right--;r.left++; m_rectBtn = r; DrawButton(&dc, m_rectBtn); } // Function name : CQComboBox::Resize // Description : Call to remove the edit and list controls // Return type : void void CQComboBox::Resize() { ASSERT (GetListBox()); CRect r; GetWindowRect(r); SetWindowPos(0, 0, 0, r.Width(), defaultSizeDY, SWP_NOMOVE | SWP_NOZORDER | SWP_NOMOVE); // Set the height and width of edit control GetClientRect(r); r.InflateRect(-1,-2); r.bottom++; r.right -= defaultSizeDX; GetEdit()->MoveWindow(r.left, r.top, r.Width(), r.Height()); // Set the height and width of list control GetWindowRect(r); int dy = r.Height(); r.top = r.bottom; r.left++;r.right--; r.bottom += m_nMultipleHeight * dy; r.right += int(m_dWidthList * r.Width()); GetListBox()->MoveWindow(r.left, r.top, r.Width(), r.Height()); } // Function name : CQComboBox::DropDown // Description : DropDown // Return type : void // Argument : BOOL bDown void CQComboBox::DropDown(BOOL bDown) { if (IsWindowVisible()) if (IsDropedDown() != bDown) { Resize(); LoadPartial(0, +GetVisibleCount()); GetListBox()->ShowWindow(bDown ? SW_SHOW : SW_HIDE); if (bDown) GetEdit()->SetFocus(); } } // Function name : CQComboBox::IsDropedDown // Description : If the list control is dropped downd, return TRUE // Return type : BOOL BOOL CQComboBox::IsDropedDown() { return GetListBox()->IsWindowVisible(); } // Function name : CQComboBox::OnWindowPosChanged // Description : // Return type : void // Argument : WINDOWPOS FAR* lpwndpos void CQComboBox::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) { CWnd::OnWindowPosChanged(lpwndpos); Resize(); } // Function name : CQComboBox::OnLButtonDown // Description : // Return type : void // Argument : UINT nFlags // Argument : CPoint point void CQComboBox::OnLButtonDown(UINT nFlags, CPoint point) { if (m_rectBtn.PtInRect(point)) { SetButton(); DropDown(!IsDropedDown()); } CWnd::OnLButtonDown(nFlags, point); } // Function name : CQComboBox::OnLButtonUp // Description : // Return type : void // Argument : UINT nFlags // Argument : CPoint point void CQComboBox::OnLButtonUp(UINT nFlags, CPoint point) { ReleaseButton(); CWnd::OnLButtonUp(nFlags, point); } // Function name : CQComboBox::OnMouseMove // Description : // Return type : void // Argument : UINT nFlags // Argument : CPoint point void CQComboBox::OnMouseMove(UINT nFlags, CPoint point) { if (m_bCaptured) { CPoint p; ::GetCursorPos(&p); ScreenToClient(&p); if (!m_rectBtn.PtInRect(p)) ReleaseButton(); } CWnd::OnMouseMove(nFlags, point); } // Function name : CQComboBox::ReleaseButton // Description : Call to release the capture and image of button. After SetButton() // Return type : void void CQComboBox::ReleaseButton() { if (m_bCaptured) { ReleaseCapture(); CDC* pDC = GetDC(); DrawButton(pDC, m_rectBtn); ReleaseDC(pDC); m_bCaptured = FALSE; } } // Function name : CQComboBox::SetButton // Description : // Return type : void void CQComboBox::SetButton() { if (!m_bCaptured) { SetCapture(); CDC* pDC = GetDC(); DrawButton(pDC, m_rectBtn, TRUE); ReleaseDC(pDC); m_bCaptured = TRUE; } } // Function name : CQComboBox::ForwardMessage // Description : This function is called by ListBoxWindowProc // Return type : void // Argument : UINT nMsg // Argument : WPARAM wParam // Argument : LPARAM lParam BOOL CQComboBox::ForwardMessage(UINT nMsg, WPARAM wParam, LPARAM lParam) { ASSERT (GetListBox()); switch (nMsg) { case WM_MOUSEMOVE: case WM_LBUTTONDOWN: { BOOL bOutside = TRUE; int nIndex = GetListBox()->ItemFromPoint(CPoint(LOWORD(wParam), HIWORD(lParam)), bOutside); if (GetCurrentItem() != nIndex) SetCurrentItem(nIndex); if (nMsg == WM_LBUTTONDOWN) { DropDown(FALSE); SelectCurrentItem(); } break; } case WM_VSCROLL: { CListBox* pListBox = GetListBox(); UINT nScrollCode = (int) LOWORD(wParam); int nHM = NULL, nStep = NULL; switch ( nScrollCode ) { case SB_LINEDOWN: case SB_PAGEDOWN: { nHM = GetVisibleCount(); nStep = (nScrollCode == SB_LINEDOWN ? 1 : nHM); } case SB_PAGEUP: case SB_LINEUP: { if (!nHM) { nHM = -GetVisibleCount(); nStep = (nScrollCode == SB_LINEUP ? -1 : nHM); } int nPos = pListBox->GetTopIndex(); LoadPartial( nPos, nHM); pListBox->SetTopIndex(nPos + nStep); pListBox->SetScrollPos(SB_VERT, pListBox->GetTopIndex()); break; } case SB_THUMBPOSITION: { int nPos = LoadPartial(HIWORD(wParam), GetVisibleCount()); pListBox->SetScrollPos(SB_VERT, HIWORD(wParam)); pListBox->SetTopIndex(nPos); break; } } return FALSE; break; } } return TRUE; } // Function name : CQComboBox::OnSetFocus // Description : When control have focus then edit will take the focus // Return type : void // Argument : CWnd* pOldWnd void CQComboBox::OnSetFocus(CWnd* pOldWnd) { CWnd::OnSetFocus(pOldWnd); GetEdit()->SetFocus(); } // Function name : CQComboBox::OnCommand // Description : When something is happen in edit control, notify the list control // Return type : BOOL // Argument : WPARAM wParam // Argument : LPARAM lParam BOOL CQComboBox::OnCommand(WPARAM wParam, LPARAM lParam) { if (LOWORD(wParam) == IDEDIT) if (HIWORD(wParam) == EN_CHANGE) { ASSERT( GetEdit() && GetEdit()->GetDlgCtrlID() == IDEDIT); CString text,t ; GetEdit()->GetWindowText(t); Search(t); } return CWnd::OnCommand(wParam, lParam); } // Function name : CQComboBox::Search // Description : Look for the lpszFindItem // Return type : void // Argument : LPCTSTR lpszFindItem void CQComboBox::Search(LPCTSTR lpszFindItem) { if (CListBox* pListBox = GetListBox()) { LoadPartial(0, GetVisibleCount()); int nItem = pListBox->FindString(-1, lpszFindItem); if (nItem < 0) { int tLine = LinePartial(lpszFindItem); LoadPartial(tLine - GetVisibleCount(), 2 * GetVisibleCount()); nItem = pListBox->FindString(-1, lpszFindItem); } SetCurrentItem(nItem); } } // Function name : CQComboBox::SelectCurrentItem // Description : Select the current item of list. Called if user click the mouse, oor press ENTER // Return type : void void CQComboBox::SelectCurrentItem() { int nIndex = GetCurrentItem(); if (nIndex != LB_ERR) { CString sItem; GetListBox()->GetText(nIndex, sItem); GetListBox()->SetScrollPos(SB_VERT, GetListBox()->GetTopIndex()); GetEdit()->SetWindowText(sItem); //Notify the parent that one item was changed if (nIndex >= 0) if (CWnd* pParent = GetParent()) pParent->SendMessage(m_nSelChange, (WPARAM)GetDlgCtrlID(), (LPARAM)m_hWnd); } } // Function name : CQComboBox::GetCurrentItem // Description : Get current item from list control // Return type : int int CQComboBox::GetCurrentItem() { return GetListBox()->GetCurSel(); } // Function name : CQComboBox::SetCurrentItem // Description : Set current item from list control to nIndex // Return type : void // Argument : int nIndex void CQComboBox::SetCurrentItem(int nIndex) { GetListBox()->SetCurSel(nIndex); } // Function name : CQComboBox::OnCreate // Description : Call OnInit if control is created dynamically // Return type : int // Argument : LPCREATESTRUCT lpCreateStruct int CQComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; OnInit(); return 0; } // Function name : CQComboBox::SetRateWidth // Description : This function will changes the width of inside listcontrol // Return type : double // Argument : double dWidthList double CQComboBox::SetRateWidth(double dWidthList) { double dResult = m_dWidthList; m_dWidthList = fabs(dWidthList); return dResult; } // Function name : CQComboBox::SetMultipleHeight // Description : // Return type : int // Argument : int nMHeight int CQComboBox::SetMultipleHeight(int nMHeight) { int nResult = m_nMultipleHeight; m_nMultipleHeight = abs(nMHeight); if (::IsWindow(m_hWnd)) { Resize(); m_nCountVisible = GetVisibleCount(); } return nResult; } // Function name : CQComboBox::GetCountItem // Description : // Return type : int int CQComboBox::GetCountItem() { return m_nCountItems; } // Function name : CQComboBox::SetCountItems // Description : Set the count of items list box. // Return type : void // Argument : int nCount void CQComboBox::SetCountItems(int nCount) { // Already, you must call GetVisibleCount() ASSERT (m_nCountVisible != 0); m_nCountItems = nCount; // If this need vertical scroll bar, I will put WS_VSCROLL style if ( m_nCountItems >= m_nCountVisible) { CWnd* pWnd = GetListBox(); // Already you must call OnInit, in fact, you must call SubclassDlgItem , or Create function ASSERT (pWnd != NULL); pWnd->ModifyStyle(0, WS_VSCROLL); SCROLLINFO sInfo; sInfo.cbSize = sizeof(sInfo); sInfo.fMask = SIF_ALL; sInfo.nMin = 0; sInfo.nMax = m_nCountItems - 1; sInfo.nPage = m_nCountVisible - 1; sInfo.nPos = 0; sInfo.nTrackPos = 0; pWnd->SetScrollInfo(SB_VERT, &sInfo); } } // Function name : CQComboBox::GetVisibleCount // Description : Get count of visible items. // Return type : int int CQComboBox::GetVisibleCount() { CListBox* pListBox = GetListBox(); ASSERT( pListBox ); CRect r; if (pListBox->GetItemRect(0, r) == LB_ERR) { int nItem = pListBox->AddString(_T("")); pListBox->GetItemRect(0, r); pListBox->DeleteString(nItem); } CRect rClient; pListBox->GetClientRect(rClient); return rClient.Height() / r.Height() + 1; } // Function name : CQComboBox::AlreadyLoadPartialListBox // Description : // Return type : void // Argument : int nLineFrom // Argument : int nHowMany int CQComboBox::AlreadyLoadPartialListBox(int nLineFrom, int nHowMany) { //Already the load was made return nLineFrom; } // Function name : CQComboBox::GetFirstQComboBox // Description : Statical function. Return first element as QComboBox // Return type : CQComboBox* CQComboBox* CQComboBox::GetFirstQComboBox() { if (POSITION position = m_mapUnloadedQCombos.GetStartPosition()) { CQComboBox* pCombo = NULL; BOOL bLoaded = TRUE; m_mapUnloadedQCombos.GetNextAssoc(position, pCombo, bLoaded); return pCombo; } return NULL; } // Function name : CQComboBox::OnTimer // Description : // Return type : void // Argument : UINT nIDEvent void CQComboBox::OnTimer(UINT nIDEvent) { switch (nIDEvent) { case QIDTIMERSTARTLOADITEMS: { KillTimer(QIDTIMERSTARTLOADITEMS); SetTimer(QIDTIMERLOADITEMS, QTIMELOADITEMS, NULL); } case QIDTIMERLOADITEMS: { POSITION position = m_mapUnloadedQCombos.GetStartPosition(); while (position) { CQComboBox* pCombo = NULL; BOOL bLoaded = TRUE; m_mapUnloadedQCombos.GetNextAssoc(position, pCombo, bLoaded); if (pCombo->IsAlreadyLoad()) m_mapUnloadedQCombos.RemoveKey(pCombo); else { pCombo->LoadPartial(0, GetVisibleCount()); } } break; } } CWnd::OnTimer(nIDEvent); } // Function name : CQComboBox::IsAlreadyLoad // Description : Return TRUE if listvox is already loaded. // Return type : BOOL BOOL CQComboBox::IsAlreadyLoad() { return m_fctLoadFunction == AlreadyLoadPartialListBox; } // Function name : CQComboBox::LoadPartial // Description : // Return type : void // Argument : int nLineFrom // Argument : int nHowMany int CQComboBox::LoadPartial(int nLineFrom, int nHowMany) { return (this->*m_fctLoadFunction)(nLineFrom, nHowMany); } // Function name : CQComboBox::LoadPartialListBox // Description : // Return type : void int CQComboBox::LoadPartialListBox(int nLineFrom, int nHowMany) { return m_QuickLoader.Load(nLineFrom, nHowMany); } // Function name : CQComboBox::Line // Description : Return line nLine, by calling own statical function // Return type : LPCTSTR // Argument : int nLine // Argument : LPARAM & lParam LPCTSTR CQComboBox::Line(int nLine, LPARAM& lParamItem) { return m_fctLine(nLine, lParamItem, m_lParam); } // Function name : CQComboBox::LinePartial // Description : return the index of real line, which has string equal with lpszItemPartial // Return type : int // Argument : LPCTSTR lpszItemPartial int CQComboBox::LinePartial(LPCTSTR lpszItemPartial) { if (m_fctLinePartial) return m_fctLinePartial(lpszItemPartial, m_lParam); return 0; } //QSnapLoader implementation int CQComboBox::QSnapLoader::SNodeItemsInfo::m_nCountRef = 0; // Function name : CQComboBox::QSnapLoader::~QSnapLoader // Description : virtual destructor // Return type : CQComboBox::QSnapLoader::~QSnapLoader() { SNodeItemsInfo* pNodeNext = m_pFirstNode; while (pNodeNext) { SNodeItemsInfo* pNodeDelete = pNodeNext; pNodeNext = pNodeNext->m_pNextNode; delete pNodeDelete; }; } // Function name : CQComboBox::QSnapLoader::QSnapLoader // Description : default constructor // Return type : CQComboBox::QSnapLoader::QSnapLoader() { m_pFirstNode = new SNodeItemsInfo(0,0,0); } // Function name : CQComboBox::QSnapLoader::SetParent // Description : Set the parent of this structure // Return type : void // Argument : CQComboBox * pParent void CQComboBox::QSnapLoader::SetParent(CQComboBox * pParent) { m_pParent = pParent; } // Function name : CQComboBox::QSnapLoader::GetListNodes // Description : // Return type : CString CString CQComboBox::QSnapLoader::GetListNodes() { CString text; SNodeItemsInfo* pIncreaseNode = m_pFirstNode; int s = 0; while (pIncreaseNode) { CString t; t.Format(_T("(%i,%i,%i, [%i,%i])\r\n"), pIncreaseNode->m_nItemLine, pIncreaseNode->m_nCount, pIncreaseNode->m_nItemLB, pIncreaseNode->GetLastLine(), pIncreaseNode->GetLastItem()); text += t; s += pIncreaseNode->m_nCount; pIncreaseNode = pIncreaseNode->m_pNextNode; } CString t; t.Format(_T("Count loaded: %i, Count items. listbox() %i"), s, m_pParent->GetListBox()->GetCount()); text += t; return text; } // Function name : CQComboBox::QSnapLoader::Load // Description : // Return type : void // Argument : int nItemFrom // Argument : int nHowMany // This function will return the real position into listbox. int CQComboBox::QSnapLoader::Load(int nItemFrom, int nHowMany) { int nIF = abs(nItemFrom + (nHowMany < 0 ? nHowMany : 0)); int nHM = abs(nHowMany), nResult = nItemFrom; CWnd* pWndParentWindowOfCombo = m_pParent->GetParent(); if (nHM = min(nHM, max(0,m_pParent->GetCountItem() - nIF))) { //Something must load ASSERT (nHM != NULL); SNodeItemsInfo* pNodeNext = m_pFirstNode; SNodeItemsInfo* pNodePrev = NULL; // Already the constructor was called ASSERT (pNodeNext); //Find the nodes ie pPrevNext->m_nItemLine <= nIF < pPrevNext->m_nItemLine while (pNodeNext && (nIF >= pNodeNext->m_nItemLine)) { pNodePrev = pNodeNext; pNodeNext = pNodeNext->m_pNextNode; } // If in the first block , number of items count is equal with total number of items, // then this function will not be called again. The next function that will //be called will be AlreadyLoadPartialListBox. if (m_pFirstNode->m_nCount == m_pParent->GetCountItem()) { m_pParent->m_fctLoadFunction = m_pParent->AlreadyLoadPartialListBox; return nItemFrom; } LPCTSTR lpszItemLB = NULL; LPARAM lParam = NULL; int nFirst = pNodePrev->GetLastLine(), nItem = pNodePrev->GetLastItem(); CListBox* pListBox = m_pParent->GetListBox(); nResult = pNodePrev->GetLastItem(); if (pNodeNext == NULL) { // After the prev node do not exist another node. BOOL bEnd = TRUE; if (nIF > nFirst) { SNodeItemsInfo* sThis = pNodePrev; pNodePrev = new SNodeItemsInfo(nIF,0, nResult ); sThis->m_pNextNode = pNodePrev; pNodePrev->m_pPrevNode = sThis; nFirst = nIF; bEnd = FALSE; } else { nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine; } NotifyWindow(pWndParentWindowOfCombo, m_nLoading, m_pParent->m_hWnd, nFirst); int i = 0; for (i = 0; (lpszItemLB = m_pParent->Line(nFirst + i, lParam)) && (i < nHM); i++) { pListBox->SetItemData(nItem = pListBox->InsertString(nItem, lpszItemLB), lParam); pNodePrev->m_nCount++; nItem++; } NotifyWindow(pWndParentWindowOfCombo, m_nLoaded, m_pParent->m_hWnd, i); } else { SNodeItemsInfo* pIncreaseNode = pNodeNext->m_pNextNode; int nDiff = pNodeNext->m_nItemLine - nFirst; ASSERT ( nDiff >= 0 ); nItem = nResult; // first item that will be inserted // {...+..} ___ {...+..} if (nDiff <= nHM) { // The real nHM will be the diference between nHowMany - nDiff nHM = nDiff; // Try to restrict these node in only one. pNodePrev->m_nCount += pNodeNext->m_nCount + nHM; pNodePrev->m_pNextNode = pNodeNext->m_pNextNode; delete pNodeNext; nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine; } else { // nFirst // /--- > nHM --\ // {...+..} __+________{......} if (nIF < nFirst) { nResult = pNodePrev->m_nItemLB + nIF - pNodePrev->m_nItemLine; nFirst = pNodePrev->GetLastLine(); pNodePrev->m_nCount += nHM; pIncreaseNode = pNodeNext; } // {......} ______+___ {...+...} else if (nIF + nHM >= pNodeNext->m_nItemLine) { nHM = pNodeNext->m_nItemLine - nIF; pNodeNext->m_nItemLine = nIF; pNodeNext->m_nCount += nHM; //pNodeNext->m_nItemLB remains constant nItem = pNodeNext->m_nItemLB; nFirst = nIF; nResult = pNodeNext->m_nItemLB; } // {......} __+____+___ {......} else { SNodeItemsInfo* sThis = new SNodeItemsInfo(nIF, nHM, nResult ); sThis->m_pPrevNode = pNodePrev; sThis->m_pNextNode = pNodeNext; pNodePrev->m_pNextNode = sThis; pNodeNext->m_pPrevNode = sThis; nFirst = nIF; pIncreaseNode = pNodeNext; } } // if some items must insert, do it if (nHM > 0) { NotifyWindow(pWndParentWindowOfCombo, m_nLoading, m_pParent->m_hWnd, nFirst); for (int i = 0; i < nHM; i++) { lpszItemLB = m_pParent->Line(nFirst + i, lParam); // while pNodePrev and pNodeNext exist ! ASSERT (lpszItemLB); pListBox->SetItemData(nItem = pListBox->InsertString(nItem, lpszItemLB), lParam); nItem++; } while (pIncreaseNode) { pIncreaseNode->m_nItemLB += nHM; pIncreaseNode = pIncreaseNode->m_pNextNode; } NotifyWindow(pWndParentWindowOfCombo, m_nLoaded, m_pParent->m_hWnd, nHM); } } } return nResult; } // Function name : CQComboBox::QSnapLoader::GetItemLine // Description : return the real line, converts from nItemLB // Return type : int // Argument : int nItemLB int CQComboBox::QSnapLoader::GetItemLine(int nItemLB) { nItemLB = max(0,nItemLB); SNodeItemsInfo* pNodeNext = m_pFirstNode; while (pNodeNext && ( pNodeNext->m_nItemLB > nItemLB )) pNodeNext = pNodeNext->m_pNextNode; return pNodeNext->m_nItemLine + nItemLB - pNodeNext->m_nItemLB; }